//////#include<bits/stdc++.h>
//////using namespace std;
//////int main()
//////{
//////	int n, m;
//////	cin >> n >> m;
//////	int maze[n][n];
//////
//////	for (int i = 0; i < n; i++) {
//////		string s;
//////		cin >> s;
//////		for (int j = 0; j < n; j++) {
//////			maze[i][j] = s[j] - '0';
//////		}
//////	}
//////	int x, y;
//////	int bx[4] = {1, -1, 1, -1};
//////	int by[4] = {1, -1, -1, 1};
//////	for (int i = 0; i < m; i++) {
//////		cin >> x >> y;
//////		queue<int> qx, qy;
//////		int a[n][n];// 记录访问
//////		memset(a, 0, sizeof(a));
//////		qx.push(x);
//////		qy.push(y);
//////		int cnt = 0;
//////		while (!qx.empty()) {
//////			for (int i = 0; i < 4; i++) {
//////				int ax = qx.front();
//////				int ay = qy.front();
//////				int tx = qx.front() + bx[i];
//////				int ty = qy.front() + by[i];
//////				if (tx < 0 || ty < 0 || tx >= n || ty >= n || a[tx][ty] == 1 || maze[tx][ty] == maze[ax][ay] ) {
//////					continue;
//////				}
//////				a[tx][ty] = 1;
//////				qx.push(tx);
//////				qy.push(ty);
//////				cnt ++;
//////			}
//////			qx.pop();
//////			qy.pop();
//////		}
//////		cout << cnt;
//////	}
//////	return 0;
//////}
//#include <iostream>
//#include <vector>
//#include <queue>
//using namespace std;
//
//int main()
//{
//	cin.tie(0);
//	ios::sync_with_stdio(false);
//	int n, m;
//	cin >> n >> m;
//
//	// 读取迷宫内容
//	vector<vector<int>> maze(n, vector<int>(n));
//	for (int i = 0; i < n; i++) {
//		string row;
//		cin >> row;
//		for (int j = 0; j < n; j++) {
//			maze[i][j] = row[j] - '0';
//		}
//	}
//
//	// 处理每个询问
//	for (int i = 0; i < m; i++) {
//		int x, y;
//		cin >> x >> y;
//
//		// 创建二维数组记录访问状态
//		vector<vector<bool>> visited(n, vector<bool>(n, false));
//
//		// 广度优先搜索
//		queue<pair<int, int>> q;
//		q.push({x, y});
//		visited[x - 1][y - 1] = true;
//
//		int count = 1;  // 计数器，初始为1（包括起始格子）
//		while (!q.empty()) {
//			int curX = q.front().first;
//			int curY = q.front().second;
//			q.pop();
//
//			// 检查上、下、左、右四个相邻格子
//			vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
//			for (auto dir : directions) {
//				int newX = curX + dir.first;
//				int newY = curY + dir.second;
//				if (newX >= 1 && newX <= n && newY >= 1 && newY <= n &&
//				    !visited[newX - 1][newY - 1] && maze[newX - 1][newY - 1] != maze[curX - 1][curY - 1]) {
//					q.push({newX, newY});
//					visited[newX - 1][newY - 1] = true;
//					count++;
//				}
//			}
//		}
//
//		cout << count << endl;
//	}
//
//	return 0;
//}
//
////#include <iostream>
////#include <vector>
////using namespace std;
////
////void dfs(vector<vector<int>>& maze, vector<vector<bool>>& visited, int x, int y, int& count) {
////	int n = maze.size();
////
////	// 检查坐标是否合法
////	if (x < 0 || x >= n || y < 0 || y >= n || visited[x][y]) {
////		return;
////	}
////
////	visited[x][y] = true;  // 标记当前单元格为已访问
////	count++;
////
////	// 检查上、下、左、右四个相邻单元格
////	vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
////	for (auto dir : directions) {
////		int newX = x + dir.first;
////		int newY = y + dir.second;
////		if (newX >= 0 && newX < n && newY >= 0 && newY < n && maze[newX][newY] != maze[x][y]) {
////			dfs(maze, visited, newX, newY, count);
////		}
////	}
////}
////
////int main() {
////	cin.tie(0);
////	ios::sync_with_stdio(false);
////	int n, m;
////	cin >> n >> m;
////
////	// 读取迷宫内容
////	vector<vector<int>> maze(n, vector<int>(n));
////	for (int i = 0; i < n; i++) {
////		string row;
////		cin >> row;
////		for (int j = 0; j < n; j++) {
////			maze[i][j] = row[j] - '0';
////		}
////	}
////
////	// 处理每个询问
////	for (int i = 0; i < m; i++) {
////		int x, y;
////		cin >> x >> y;
////
////		vector<vector<bool>> visited(n, vector<bool>(n, false));
////
////		int count = 0;
////		dfs(maze, visited, x - 1, y - 1, count);  // 将坐标减去1以与数组索引对应
////
////		cout << count << endl;
////	}
////
////	return 0;
////}
//////1mle 2tle
#include <bits/stdc++.h>
using namespace std;
#define check(x,y) (x>0&&x<=n &&y>0 &&y<=n) // 检查是否越界
#define nx (x+dx[i])// 根据方向移动后的新 x 坐标
#define ny (y+dy[i])// 根据方向移动后的新 y 坐标

char a[1005][1005];
int f[1005][1005];
bool v[1005][1005];
int n, m, dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1}, now;
int ans[1000005][2], Count;
void dfs(int x, int y)
{
	now++;
	ans[now][0] = x, ans[now][1] = y;
	// 深度优先搜索四个方向
	for (int i = 0; i < 4; i++) {
		if (check(nx, ny) && !v[nx][ny] && a[x][y] != a[nx][ny]) {
			v[nx][ny] = true;
			dfs(nx, ny);
		}
	}
}

int res;
char ch;

// 快速读入一个整数
inline int read()
{
	res = 0;
	while (isspace(ch = getchar()));
	do res = res * 10 + ch - '0';
	while (isdigit(ch = getchar()));
	return res;
}

// 快速输出一个整数
inline void write(int n)
{
	if (n == 0) return;
	write(n / 10);
	putchar(n % 10 + '0');
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%s", a[i] + 1);

	// 搜索每一个连通块
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) if (!v[i][j]) {
				v[i][j] = true;
				now = 0;
				dfs(i, j);

				// 标记每个连通块的大小
				for (int i = 1; i <= now; i++) f[ans[i][0]][ans[i][1]] = now;
			}

	int x, y;
	for (int i = 1; i <= m; i++) {
		x = read();
		y = read();
		write(f[x][y]);
		putchar('\n');
	}
	return 0;
}
